home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1997
/
MacHack 1997.toast
/
Hacks
/
Hacks ’96
/
FontMancer
/
Common
/
Display.c
< prev
next >
Wrap
Text File
|
1996-06-21
|
9KB
|
328 lines
/***********************************************************************
#
# displays.c
#
# This segment handles the Display Manager notification and
# repositions application windows in response.
#
# Author: Michael Marinkovich
# Apple Developer Technical Support
#
#
# Modification History:
#
# 10/12/95 MWM Initial coding
# 4/22/96 WCS Tweaked it for use in my program.
# DO NOT USE in your code, refer to
# develop issue 18 or Apple's web
# site for original code.
#
#
# Copyright © 1992-95 Apple Computer, Inc., All Rights Reserved
#
#
***********************************************************************/
#include "Display.h"
extern WindowPtr gMainWindow;
//----------------------------------------------------------------------
//
// InstallAEDMNotification - tell DM that we want to be notified by AE.
//
//
//----------------------------------------------------------------------
OSErr InstallAEDMNotification(void)
{
OSErr err;
err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice,
NewAEEventHandlerProc(DoAEDisplayUpdate),
0L, false);
return err;
}
//----------------------------------------------------------------------
//
// DoAEDisplayUpdate - Display Manager calls this proc when a depth or
// mode change is made. Your application should
// handle window repositioning here.
//----------------------------------------------------------------------
pascal OSErr DoAEDisplayUpdate(AppleEvent *event,AppleEvent *reply,long refCon)
{
OSErr err;
err = HandleNotification(event);
return noErr;
}
//----------------------------------------------------------------------
//
// HandleNotification - handle the AppleEvent returned by either the
// callback or the AppleEvent procedure.
//
//----------------------------------------------------------------------
OSErr HandleNotification(AppleEvent *event)
{
OSErr err;
GrafPtr oldPort;
AEDescList displayList;
AEDescList aDisplay;
AERecord oldConfig,newConfig;
AEKeyword tempWord;
DisplayIDType displayID;
unsigned long returnType;
long count;
Rect oldRect, newRect;
GDHandle gd;
GetPort(&oldPort);
// Get a list of the displays from the Display Notice AppleEvent.
err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList);
// How many items in the list
err = AECountItems(&displayList,&count);
while (count > 0) { // Loop through the list.
err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord,
&aDisplay);
// Get the Old Rect.
err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord,
&oldConfig);
err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard,
&returnType, &oldRect, 8, nil);
// Get the DisplayID so we can get the GDevice later.
err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard,
&returnType, &displayID, 8, nil);
// Get the New Rect.
err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord,
&newConfig);
err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard,
&returnType, &newRect, 8, nil);
// If the New and Old rects are not the same then we can assume
// the GDevice has changed and we need to rearrange the windows.
if (err == noErr && !EqualRect(&newRect, &oldRect)) {
err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
HandleDeviceChange(gd, &newRect);
}
count--;
err = AEDisposeDesc(&aDisplay);
err = AEDisposeDesc(&oldConfig);
err = AEDisposeDesc(&newConfig);
}
err = AEDisposeDesc(&displayList);
SetPort(oldPort);
return err;
}
//----------------------------------------------------------------------
//
// HandleDeviceChange - called when the oldconfig is different from
// newconfig. Will check all windows on effected
// device and move if needed.
//----------------------------------------------------------------------
OSErr HandleDeviceChange(GDHandle gd, Rect *newRect)
{
OSErr err = noErr;
//GDHandle gd;
GDHandle onGD;
WindowRef window;
// Get the GDevice from the DisplayID.
//err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
//if (err == noErr && gd != nil) {
window = gMainWindow;
SetPort(window);
// which device holds the greatest portion of the window
onGD = GetGreatestDevice(window);
// If the window is not 50% or greater on
// the desired device then pass it up.
if (onGD == gd)
if (OutOfBoundsRect(gd, window, *newRect))
MoveInbounds(window, gd, *newRect);
//}
return err;
}
//----------------------------------------------------------------------
//
// OutOfBoundsRect - check to see if the window is out of the device
// rect.
//
//----------------------------------------------------------------------
Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect)
{
Boolean out = false;
Rect windRect;
short mHeight = 0;
GetWindowRect(window, &windRect);
if (gd == GetMainDevice())
mHeight = GetMBarHeight();
if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
out = true;
if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top + mHeight))
out = true;
return out;
}
//----------------------------------------------------------------------
//
// MoveInbounds - Move window on to desired device
//
//
//----------------------------------------------------------------------
void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
{
Rect bounds;
short mHeight = 0;
short hGlobal;
short vGlobal;
GetWindowRect(window, &bounds);
if (gd == GetMainDevice())
mHeight = GetMBarHeight();
hGlobal = bounds.left;
vGlobal = bounds.top + kTitleBarHeight;
// we want to make the left-top a priority so adjust it first
// as to override the bottom, right movements. This is so we
// can resize the window later.
if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
((bounds.bottom - bounds.top) >
((screenRect.bottom - screenRect.top) - mHeight))) {
// adjust left
if (bounds.left < screenRect.left)
hGlobal = screenRect.left + kFudgeFactor;
// adjust top
if (bounds.top < screenRect.top + mHeight)
vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
}
else {
// adjust left
if (bounds.left < screenRect.left)
hGlobal = screenRect.left + kFudgeFactor;
else {
// adjust right
if (bounds.right > screenRect.right)
hGlobal = (screenRect.right - (bounds.right - bounds.left)) - kFudgeFactor;
}
// adjust top
if (bounds.top < screenRect.top + mHeight)
vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
else {
// adjust bottom
if (bounds.bottom > screenRect.bottom)
vGlobal = (screenRect.bottom - kFudgeFactor -
(bounds.bottom - bounds.top) + mHeight);
}
}
MoveWindow(window, hGlobal, vGlobal,false);
}
//----------------------------------------------------------------------
//
// GetGreatestDevice - find thw device that holds the greatest area
// of the window.
//
//----------------------------------------------------------------------
GDHandle GetGreatestDevice(WindowRef window)
{
GDHandle gd;
GDHandle savedGD;
Rect gdRect;
Rect foundRect;
long size;
long greatest = nil;
gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
savedGD = gd;
// Loop through the device list
while (gd != nil) {
gdRect = (**gd).gdRect;
GlobalToLocal(&topLeft(gdRect));
GlobalToLocal(&botRight(gdRect));
if (SectRect(&window->portRect, &gdRect, &foundRect)) {
size = ((long)(foundRect.right - foundRect.left) *
(long)(foundRect.bottom - foundRect.top));
if (size > greatest) {
greatest = size;
savedGD = gd; // save the greatest device
}
}
gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
}
return savedGD;
}
//----------------------------------------------------------------------
//
// GetWindowRect - return actual window rect in global coords
//
//
//----------------------------------------------------------------------
void GetWindowRect(WindowRef window, Rect *windRect)
{
*windRect = window->portRect;
// add the titlebar height for actual height
windRect->top -= kTitleBarHeight;
LocalToGlobal(&TopLeft(*windRect));
LocalToGlobal(&BotRight(*windRect));
}